package com.whale.web.json.tree;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.context.MessageSource;
import org.springframework.ui.Model;

import com.whale.constants.MenuGroupConstants;
import com.whale.kernel.domain.HtmlMenu;
import com.whale.kernel.domain.HtmlPage;
import com.whale.kernel.model.pagination.PagedList;
import com.whale.kernel.model.pagination.Step;
import com.whale.kernel.model.tree.HtmlPageLeaf;
import com.whale.kernel.model.tree.LevelLimiter;
import com.whale.kernel.model.tree.Tree;
import com.whale.kernel.model.tree.TreeNode;
import com.whale.kernel.service.HtmlMenuService;
import com.whale.kernel.service.HtmlPageService;

public class MenuTreeJsonProcessor {

	private final HtmlPageService htmlPageService;
	private final HtmlMenuService htmlMenuService;
	private final MessageSource messages;

	public MenuTreeJsonProcessor(HtmlPageService htmlPageService,
			HtmlMenuService htmlMenuService, MessageSource messages) {
		this.htmlPageService = htmlPageService;
		this.htmlMenuService = htmlMenuService;
		this.messages = messages;
	}

	public JSONObject getLeafPageJSON(String menuPath) throws JSONException {
		Step step = new Step(10, 0);
		PagedList<HtmlPage> pagedLeafs = htmlPageService.findHtmlPages(
				menuPath, new Step(10, 0));
		JSONObject leafPage = new JSONObject();
		leafPage.put("pageNum", 1);
		leafPage.put("offset", step.getOffset());
		leafPage.put("total", pagedLeafs.getTotal());
		JSONObject leafs = new JSONObject();
		for (HtmlPage htmlPage : pagedLeafs.getResult()) {
			leafs.put(htmlPage.getPageId(), Arrays.asList(htmlPage.getTitle(),
					htmlPage.getModificationDate().toString()));
		}
		leafPage.put("leafs", leafs);
		return leafPage;
	}

	public JSONObject getMenuNodeJSON(HtmlMenu htmlMenu, LevelLimiter limiter)
			throws JSONException {
		String menuName = messages.getMessage(htmlMenu.getNameCode(),
				new Object[] {}, null);
		JSONObject menuNode = new JSONObject();
		menuNode.put("title", menuName);
		if (!limiter.canNext()) {
			return menuNode;
		}
		menuNode.put("path", htmlMenu.getPath());
		menuNode.put("leafPage", getLeafPageJSON(htmlMenu.getPath()));
		limiter.increase();
		menuNode.put("subnodes",
				getMenuSubNodeJSON(htmlMenu.getPath(), limiter));
		limiter.decrease();
		return menuNode;
	}

	public JSONObject getMenuSubNodeJSON(String parentMenuPath,
			LevelLimiter limiter) throws JSONException {
		JSONObject subnodes = new JSONObject();

		List<HtmlMenu> subMenus = htmlMenuService
				.getSubHtmlMenus(parentMenuPath);
		for (HtmlMenu subMenu : subMenus) {
			subnodes.put("node_" + subMenu.getId().toString(),
					getMenuNodeJSON(subMenu, limiter));
		}
		return subnodes;
	}

	public void populateTreeMenu(Model model) throws JSONException {
		JSONObject topNodeJSON = new JSONObject();
		Tree<HtmlPageLeaf> treeModel = new Tree<HtmlPageLeaf>();
		List<TreeNode<HtmlPageLeaf>> topNodes = new ArrayList<TreeNode<HtmlPageLeaf>>();
		TreeNode<HtmlPageLeaf> topNode = new TreeNode<HtmlPageLeaf>();
		List<TreeNode<HtmlPageLeaf>> subtopNodes = new ArrayList<TreeNode<HtmlPageLeaf>>();

		String topNodeName = messages.getMessage("menu.group.user",
				new Object[] {}, null);
		topNodeJSON.put("title", topNodeName);
		topNode.setName(topNodeName);
		topNode.setNodeId("topnode");
		topNodes.add(topNode);
		topNode.setSubnodes(subtopNodes);

		List<HtmlMenu> userTopLevelMenus = htmlMenuService
				.getTopLevelHtmlMenus(MenuGroupConstants.USER_MENU_GROUP_ID);
		JSONObject topSubnodes = new JSONObject();
		LevelLimiter limiter = new LevelLimiter();
		for (HtmlMenu menu : userTopLevelMenus) {
			String nodeId = "node_" + menu.getId().toString();
			topSubnodes.put(nodeId, getMenuNodeJSON(menu, limiter));
			addTreeNode(nodeId, menu, subtopNodes);
		}
		topNodeJSON.put("subnodes", topSubnodes);
		treeModel.setTopNodes(topNodes);
		model.addAttribute("topNodeJSON",
				(new JSONObject()).put("topnode", topNodeJSON).toString());
		model.addAttribute("treeMenu", treeModel);
	}
	
	public JSONObject feedMenuNode(String path) throws JSONException {
		HtmlMenu menu = htmlMenuService.findHtmlMenu(path);
		LevelLimiter limiter = new LevelLimiter();
		return getMenuNodeJSON(menu, limiter);
	}

	private void addTreeNode(String nodeId, HtmlMenu menuElement,
			List<TreeNode<HtmlPageLeaf>> destNodes) {
		TreeNode<HtmlPageLeaf> node = new TreeNode<HtmlPageLeaf>();
		String localazedName = this.messages.getMessage(
				menuElement.getNameCode(), new Object[] {}, null);
		node.setNodeId(nodeId);
		node.setName(localazedName);
		node.setPath(menuElement.getPath());
		destNodes.add(node);
	}
}
